package apps.AfterDlcs.afterDlcsBL.hero;

import apps.AfterDlcs.AfterDlcs;
import apps.AfterDlcs.afterDlcsBL.Event;
import apps.AfterDlcs.afterDlcsBL.Keys;
import apps.AfterDlcs.afterDlcsBL.buff.BuffKeys;
import apps.AfterDlcs.afterDlcsBL.warSand.WarSand;
import apps.AfterDlcs.afterDlcsBL.buff.Buff;
import backs.dataBase.DBNormal;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class Hero {
    public int worldID,heroID;

    public Map<Integer,List<Buff>> buffMap=new HashMap<>();

    public static Map<String,Hero> heroMap=new HashMap<>();

    public WarSand warSand;
    public static Hero getHero(int worldID,int heroID)
    {
        String key=worldID+"_"+heroID;
        if(heroMap.containsKey(key))
        {
            return heroMap.get(key);
        }
        else
        {
            Hero hero=new Hero(worldID,heroID);
            heroMap.put(key,hero);
            hero.initHero();
            return hero;
        }
    }

    public Hero(int worldID, int heroID) {
        this.worldID = worldID;
        this.heroID = heroID;
    }
    public void initHero()
    {
        initWarSand();
        initBuffs();
    }

    public void initWarSand()
    {
        if(this.warSand!=null) this.warSand.removeHero(this);
        int x=Integer.parseInt(HeroBL.getHeroValue(worldID,heroID, Keys.LOCATION_X,"0",false));
        int y=Integer.parseInt(HeroBL.getHeroValue(worldID,heroID,Keys.LOCATION_Y,"0",false));
        this.warSand=WarSand.getWarSand(worldID,x,y);
        this.warSand.addHero(this);
    }

    public void handleEvent(Event event)
    {
        for(event.eventTurn=1;event.eventTurn<=event.maxTurn;event.eventTurn++)
        {
            if(!event.goOn) return;
            if(event.eventTurn%2==1) handleEventForward(event);
            else handleEventBackward(event);
        }
    }

    public void handleEventForward(Event event)
    {
        for(int i=Buff.MAX_BUFF_LEVEL;i>=1;i--)
        {
            for(Buff buff:buffMap.get(i))
            {
                if(!event.goOn) return;
                buff.handleEvent(event);
            }
        }
    }

    public void handleEventBackward(Event event)
    {
        for(int i=0;i<=Buff.MAX_BUFF_LEVEL;i++)
        {
            for(Buff buff:buffMap.get(i))
            {
                if(!event.goOn) return;
                buff.handleEvent(event);
            }
        }
    }
    public void initBuffs()
    {
        for(int i=1;i<=Buff.MAX_BUFF_LEVEL;i++)
        {
            List<Buff> buffList=new ArrayList<Buff>();
            List<String> buffs= DBNormal.getValues(AfterDlcs.dbName,worldID,"hero_"+heroID+"_buffList_level_"+i);
            for(String buffID:buffs)
            {
                Buff buff=Buff.initBuffByBuffID(this,worldID,Integer.parseInt(buffID),i);
                buffList.add(buff);
            }
            buffMap.put(i,buffList);
        }
        buffMap.put(0, Buff.getBaseBuffList(this,worldID));

    }

    public void setValue(String key,String value)
    {
        HeroBL.setHeroValue(worldID,heroID,key,value);
    }

    public String getValueByEvent(Hero watcher,Object values[])
    {
        Event watchEvent=new Event(watcher,this,this, BuffKeys.GET_VALUE,values);
        this.warSand.handleEvent(watchEvent);
        return watchEvent.values[watchEvent.values.length-1].toString();
    }

    public double getHealthByEvent(Hero watcher)
    {
        double maxHp=Double.parseDouble(this.getValueByEvent(watcher,new Object[]{HeroKeys.MAX_HP,"0"}));
        if(maxHp<=0) maxHp=1;
        double hp=Double.parseDouble(this.getValueByEvent(watcher,new Object[]{HeroKeys.HP,"0"}));
        double health=hp/maxHp;
        return health;
    }
    public void addNum(String key,int num,int maxNum,int minNum)
    {
        int old=Integer.parseInt(this.getValueByEvent(this,new Object[]{key,"0"}));
        old+=num;
        if(old<minNum) old=minNum;
        if(old>maxNum) old=maxNum;
        this.setValue(key,old+"");
    }

    public void addNum(String key,double num,double maxNum,double minNum)
    {
        double old=Double.parseDouble(this.getValueByEvent(this,new Object[]{key,"0"}));
        old+=num;
        if(old<minNum) old=minNum;
        if(old>maxNum) old=maxNum;
        this.setValue(key,old+"");
    }

    public String getValueByEvent(String key,String defaultValue)
    {
        return getValueByEvent(this,key,defaultValue);
    }

    public String getValueByEvent(String key)
    {
        return getValueByEvent(key,"0");
    }

    public String getValueByEvent(Hero watcher,String key)
    {
        return  getValueByEvent(watcher,key,"0");
    }

    public String getValueByEvent(Hero watcher,String key,String defaultValue)
    {
        return getValueByEvent(watcher,new Object[]{key,defaultValue});
    }




    public int getIntByEvent(String key,String defaultValue)
    {

        return Integer.parseInt(getValueByEvent(key,defaultValue));
    }

    public int getIntByEvent(String key)
    {
        return Integer.parseInt(getValueByEvent(key));
    }

    public int getIntByEvent(Hero watcher,String key)
    {
        return Integer.parseInt(getValueByEvent(watcher,key));
    }

    public int getIntByEvent(Hero watcher,String key,String defaultValue)
    {
        return Integer.parseInt(getValueByEvent(watcher,key,defaultValue));
    }



    public double getDoubleByEvent(String key,String defaultValue)
    {

        return Double.parseDouble(getValueByEvent(key,defaultValue));
    }

    public double getDoubleByEvent(String key)
    {
        return Double.parseDouble(getValueByEvent(key));
    }

    public double getDoubleByEvent(Hero watcher,String key)
    {
        return Double.parseDouble(getValueByEvent(watcher,key));
    }

    public double getDoubleByEvent(Hero watcher,String key,String defaultValue)
    {
        return Double.parseDouble(getValueByEvent(watcher,key,defaultValue));
    }
}
